﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using UIT.Converters;
using UIT.Style;
using System.Globalization;
using UIT.Controls;
using System.Text.RegularExpressions;

namespace UIT.Web.Renderers
{
    public static class StyleRenderer
    {
        public static void RenderBorder(this UIT.Controls.Border border, StringBuilder sb, Unit width)
        {
            if (width.IsEmpty)
                sb.Append("0px");
            else
                sb.Append(width);
            sb.Append(" solid ");
            SolidColorBrush color = border.BorderBrush as SolidColorBrush;
            if (color == null)
                throw new NotSupportedException("In web, the border brush can only be solid");
            sb.Append(ColorConverter.ToString(color.Color));
        }

        public static string RenderBackground(this Brush background)
        {
            StringBuilder sb = new StringBuilder();
            RenderBackground(background, sb);
            return sb.ToString();
        }
        public static void RenderBackground(this Brush background, StringBuilder sb)
        {
            SolidColorBrush color = background as SolidColorBrush;
            if (color != null)
            {
                if (color.Opacity == 100 && color.Color.Alpha == byte.MaxValue)
                {
                    sb.AppendFormat("; background: rgb({0}, {1}, {2});", color.Color.Red, color.Color.Green, color.Color.Blue);
                }
                else
                {
                    /* Fallback for web browsers that doesn't support RGBa */
                    sb.AppendFormat("; background: rgb({0}, {1}, {2});", color.Color.Red, color.Color.Green, color.Color.Blue);
                    sb.AppendFormat(CultureInfo.InvariantCulture, "; background: rgba({0}, {1}, {2}, {3:F});", color.Color.Red, color.Color.Green, color.Color.Blue, color.Color.Alpha / 256.0);
                    sb.AppendFormat("; filter:progid:DXImageTransform.Microsoft.gradient(startColorstr={0}, endColorstr={0})", ColorConverter.ToString(color.Color));
                    sb.AppendFormat("; -ms-filter: 'progid:DXImageTransform.Microsoft.gradient(startColorstr={0}, endColorstr={0})'", ColorConverter.ToString(color.Color));
                }
                return;
            }
            RadialGradientBrush radial = background as RadialGradientBrush;
            if (radial != null)
            {
                /* Fallback for web browsers that doesn't support RGBa */
                var mainColor = radial.GradientStops.OrderByDescending(gs => gs.Offset).First().Color;
                sb.AppendFormat("; background: rgb({0}, {1}, {2});", mainColor.Red, mainColor.Green, mainColor.Blue);

                string[] radials = { "background-image: -moz-radial-gradient(", "background-image: -webkit-radial-gradient(", "background-image: -o-radial-gradient(", "background-image: -ms-radial-gradient(", "background-image: radial-gradient(" };
                foreach (string radialProperty in radials)
                {
                    sb.Append(radialProperty);
                    sb.Append(radial.Center.X * 100);
                    sb.Append("% ");
                    sb.Append(radial.Center.Y * 100);
                    sb.Append("%, ");
                    sb.Append(radial.GradientOrigin.X * 100);
                    sb.Append("% ");
                    sb.Append(radial.GradientOrigin.Y * 100);
                    sb.Append("%, ");
                    bool isFirst = true;
                    foreach (GradientStop gs in radial.GradientStops)
                    {
                        if (isFirst)
                            isFirst = false;
                        else
                            sb.Append(',');
                        sb.Append(ColorConverter.ToString(gs.Color));
                        sb.Append(' ');
                        sb.Append(gs.Offset * 100);

                        sb.Append('%');
                    }
                    sb.Append(");");
                }
                sb.Append("background-repeat:no-repeat;");
                return;
            }
        }

        public static void BeginRenderFullStyle(this IDrawableControl control, XmlWriter writer, params string[] cssClasses)
        {
            control.RenderStyleKey(writer, cssClasses);
            control.BeginRenderStyle(writer);
        }

        public static void RenderStyleKey(this IDrawableControl control, XmlWriter writer, params string[] cssClasses)
        {
            if (control.StyleKey != null || (cssClasses != null && cssClasses.Length > 0))
            {
                if (cssClasses != null && cssClasses.Length > 0)
                    writer.WriteAttributeString("class", control.StyleKey + " " + string.Join(" ", cssClasses));
                else
                    writer.WriteAttributeString("class", control.StyleKey);
            }
        }

        private static void BeginRenderStyle(this IDrawableControl control, XmlWriter writer)
        {
            writer.WriteStartAttribute("style");
        }

        public static void EndRenderStyle(this IDrawableControl control, XmlWriter writer)
        {
            writer.WriteEndAttribute();
        }

        public static void RenderFullStyle(this IDrawableControl control, XmlWriter writer, params string[] cssClasses)
        {
            control.BeginRenderFullStyle(writer, cssClasses);
            control.Style.Render(writer);
            control.EndRenderStyle(writer);
        }

        public static void Render(this Style.Style style, XmlWriter writer)
        {
            writer.WriteRaw(Render(style));
        }

        public static string Render(this Style.Style style)
        {
            StringBuilder sb = new StringBuilder();
            if (!style.Height.IsEmpty)
                sb.Append("; height: " + style.Height);
            if (!style.Width.IsEmpty)
                sb.Append("; width: " + style.Width);
            if (!style.Text.Color.IsEmpty)
                sb.Append("; color: " + ColorConverter.ToString(style.Text.Color));
            if (!style.Text.Size.IsEmpty)
                sb.Append("; font-size: " + style.Text.Size);
            if (!style.Margin.Left.IsEmpty)
                sb.Append("; margin-left :" + style.Margin.Left);
            if (!style.Margin.Top.IsEmpty)
                sb.Append("; margin-top :" + style.Margin.Top);
            if (!style.Margin.Right.IsEmpty)
                sb.Append("; margin-right :" + style.Margin.Right);
            if (!style.Margin.Bottom.IsEmpty)
                sb.Append("; margin-bottom :" + style.Margin.Bottom);

            if (style.Background != null)
                style.Background.RenderBackground(sb);
            return sb.ToString();
        }

        internal static string GetCssProperty(string p)
        {
            switch (p)
            {
                default:
                    Regex uppercase = new Regex(@"\.?([A-Z])");
                    return uppercase.Replace(p, m => (m.Index == 0 ? "" : "-") + m.Groups[1].Value.ToLower());
            }
        }
    }
}
